package com.lbank.spiderflow.core.executor.function;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import com.lbank.spiderflow.annotation.Comment;
import com.lbank.spiderflow.annotation.Example;
import com.lbank.spiderflow.core.utils.ExtractUtils;
import com.lbank.spiderflow.executor.FunctionExecutor;
import org.springframework.stereotype.Component;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.zip.DataFormatException;
import java.util.zip.Inflater;

/**
 * 字符串内容和Base64互相转换 工具类 防止NPE
 * @author Administrator
 *
 */
@Component
@Comment("base64常用方法")
public class Base64FunctionExecutor implements FunctionExecutor{
	
	@Override
	public String getFunctionPrefix() {
		return "base64";
	}
	
	@Comment("根据byte[]进行base64加密")
	@Example("${base64.encode(resp.bytes)}")
	public static String encode(byte[] bytes){
		return bytes != null ? Base64.encodeBase64String(bytes) : null;
	}
	
	@Comment("根据String进行base64加密")
	@Example("${base64.encode(resp.bytes,'UTF-8')}")
	public static String encode(String content,String charset){
		return encode(StringFunctionExecutor.bytes(content,charset));
	}
	
	@Comment("根据String进行base64加密")
	@Example("${base64.encode(resp.html)}")
	public static String encode(String content){
		return encode(StringFunctionExecutor.bytes(content));
	}
	
	@Comment("根据byte[]进行base64加密")
	@Example("${base64.encodeBytes(resp.bytes)}")
	public static byte[] encodeBytes(byte[] bytes){
		return bytes != null ? Base64.encodeBase64(bytes) : null;
	}
	
	@Comment("根据String进行base64加密")
	@Example("${base64.encodeBytes(resp.html,'UTF-8')}")
	public static byte[] encodeBytes(String content,String charset){
		return encodeBytes(StringFunctionExecutor.bytes(content,charset));
	}
	
	@Comment("根据String进行base64加密")
	@Example("${base64.encodeBytes(resp.html)}")
	public static byte[] encodeBytes(String content){
		return encodeBytes(StringFunctionExecutor.bytes(content));
	}
	
	@Comment("根据String进行base64解密")
	@Example("${base64.decode(resp.html)}")
	public static byte[] decode(String base64){
		return base64  != null ? Base64.decodeBase64(base64) :null;
	}
	
	@Comment("根据byte[]进行base64解密")
	@Example("${base64.decode(resp.bytes)}")
	public static byte[] decode(byte[] base64){
		return base64  != null ? Base64.decodeBase64(base64) :null;
	}
	
	@Comment("根据String进行base64解密")
	@Example("${base64.decodeString(resp.html)}")
	public static String decodeString(String base64){
		return base64  != null ? new String(Base64.decodeBase64(base64)) :null;
	}
	
	@Comment("根据byte[]进行base64解密")
	@Example("${base64.decodeString(resp.bytes)}")
	public static String decodeString(byte[] base64){
		return base64  != null ? new String(Base64.decodeBase64(base64)) :null;
	}
	
	@Comment("根据byte[]进行base64解密")
	@Example("${base64.decodeString(resp.bytes,'UTF-8')}")
	public static String decodeString(byte[] base64,String charset){
		return base64  != null ? StringFunctionExecutor.newString(Base64.decodeBase64(base64),charset) :null;
	}

	@Comment("解析加密字符串")
	@Example("${base64.zlib2decode(resp.json,'$.data')}")
	public static Object zlib2decode(Object root,String jsonpath){
		try {
			Object jsonObj = null;
			if(StringUtils.isBlank(jsonpath)){
				jsonObj = root;
			}else{
				jsonObj = ExtractUtils.getValueByJsonPath(root, jsonpath);
			}
			// Decode the Base64 string to a byte array
			byte[] compressedData = java.util.Base64.getDecoder().decode(jsonObj.toString());

			// Prepare an inflater instance for decompression
			Inflater inflater = new Inflater();
			inflater.setInput(compressedData);

			// Create a buffer for the decompressed data
			ByteArrayOutputStream outputStream = new ByteArrayOutputStream(compressedData.length);
			byte[] buffer = new byte[1024];

			// Decompress the data
			while (!inflater.finished()) {
				int count = inflater.inflate(buffer);
				outputStream.write(buffer, 0, count);
			}

			// Get the decompressed data as a string
			String outputString = outputStream.toString(StandardCharsets.UTF_8);

			// Close the streams
			outputStream.close();
			inflater.end();

			return outputString;
		} catch (IOException | DataFormatException e) {
			System.out.println("root base64Str = " + root);
		}
		return null;
	}
}
